#include "PCH.h"
#include "ShaderFactory.h"
#include "FileLoader.h"
using namespace DeviousRenderer;

ShaderFactory::ShaderFactory()
{

}

ShaderFactory::~ShaderFactory()
{

}

ID3DBlob* ShaderFactory::CompileShader(ShaderType pShaderType, std::wstring& fileName, std::wstring& mainFunction, const std::map<std:;string, std::string>& environments)
{
	HRESULT hr;
	std::wstringstream message;
	UINT flags = D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
#if _DEBUG
	flags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_WARNINGS_ARE_ERRORS;
#endif
	D3D_SHADER_MACRO* pDefines = new D3D_SHADER_MACRO[environments.size()];
	int i = 0;
	for (std::map<std::string, std::string>::iterator it = environments.begin(); it != environments.end(); it ++)
	{
		pDefines[i].Name = it->first;
		pDefines[i].Definition = it->second;
	}
	FileLoader shaderFile;
	if (!shaderFile.Open(fileName))
	{
		message<<"Unable to load shader file: "<<fileName;
	}
	std::string sShaderModel;
	switch(pShaderType)
	{
	case VERTEX_SHADER:
		sShaderModel = "vs_5_0";
		break;
	case HULL_SHADER:
		sShaderModel = "hs_5_0";
		break;
	case DOMAIN_SHADER:
		sShaderModel = "ds_5_0";
		break;
	case  PIXEL_SHADER:
		sShaderModel = "ps_5_0";
		break;
	case GEOMETRY_SHADER:
		sShaderModel = "gs_5_0";
		break;
	case COMPUTER_SHADER:
		sShaderModel = "cs_5_0";
		break;
	default:
		//TODO
		break;
	}

	ID3DBlob* pCompiledShader = 0;
	ID3DBlob* pErrorMessages = 0;
	
	char asciiFunction[1024];
	WideCharToMultiByte(CP_ACP, 0, mainFunction.c_str(), -1, asciiFunction, 1024, NULL, NULL);

	if (FAILED(hr = D3DCompile(shaderFile.GetDataPtr(), shaderFile.GetDataSize(), NULL, pDefines, NULL, asciiFunction, sShaderModel.c_str(), flags, 0, &pCompiledShader, &pErrorMessages) ))
	{
		const char* errorMsg = (const char*)pErrorMessages;
		message<<"Compile shader file "<<fileName << " failed: "<<errorMsg;
		SAFE_RELEASE(pCompiledShader);
		SAFE_RELEASE(pErrorMessages);

		return NULL;
	}

	return pCompiledShader;
}


